#include "widget.h"
#include "ui_widget.h"

#include <QDebug>
#include <QElapsedTimer>
#include <QThread>

#include "cthreadsafebuffer.h"
#include "mysingleton.h"

// C++ 线程
#include <iostream>
#include <future>
#include <chrono>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    qDebug() <<__TIME__<<__FUNCTION__<<__LINE__<< "currentThreadId:" << QThread::currentThreadId() << endl;
}

Widget::~Widget()
{
    delete ui;
}

// 定义一个将在新线程中运行的函数
void threadFunctionEnqueue(quint64 len)
{
    QElapsedTimer t;
    t.start();

    // 模拟一些工作
    for (quint64 i = 0; i < len; ++i) {
        qDebug() << "enqueue:" << QByteArray::number(i + 10) << endl;
        mySingleton::instance().enqueue(QByteArray::number(i + 10));
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }

    qDebug() <<__TIME__<<__FUNCTION__<<__LINE__<< "currentThreadId:" << QThread::currentThreadId() << endl;
    qDebug() <<__TIME__<<__FUNCTION__<<__LINE__<< "Elapsed time:" << t.elapsed() << endl;
}

// 定义一个将在新线程中运行的函数
void threadFunctionDequeue(quint64 len)
{
    QElapsedTimer t;
    t.start();

    // 出队
    for (quint64 i = 0; i < len; ++i) {
        qDebug() << "dequeue:" << mySingleton::instance().dequeue() << endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }

    qDebug() <<__TIME__<<__FUNCTION__<<__LINE__<< "currentThreadId:" << QThread::currentThreadId() << endl;
    qDebug() <<__TIME__<<__FUNCTION__<<__LINE__<< "Elapsed time:" << t.elapsed() << endl;
}

// 普通单例模式-len太大界面会无响应
void Widget::on_pushButton_clicked()
{
    QElapsedTimer t;
    t.start();

    //quint64 len = 2000000; // 测试多线程极限
    quint64 len = 1000;

#if 0
    // 开启两个线程,一个入队和一个出队
    // 使用std::async创建一个异步任务
    auto futureEnqueue = std::async(std::launch::async, threadFunctionEnqueue,len);

    // 使用std::async创建一个异步任务
    auto futureDequeue = std::async(std::launch::async, threadFunctionDequeue,len);

    // 等待异步任务完成
    futureEnqueue.wait();

    // 等待异步任务完成
    futureDequeue.wait();

#elif(0)
    // 开启两个线程,一个入队和一个出队
    std::thread enqueueThread(threadFunctionEnqueue, len);
    std::thread dequeueThread(threadFunctionDequeue, len);

    // 等待两个线程完成
    enqueueThread.join();
    dequeueThread.join();
#else
    // 创建两个工作线程
    enqueueThread = new WorkerThread(len, true, this);
    dequeueThread = new WorkerThread(len, false, this);
    // 连接信号和槽
    connect(enqueueThread, &WorkerThread::dataProcessed, this, &Widget::handleDataProcessedSlot, Qt::QueuedConnection);
    connect(dequeueThread, &WorkerThread::dataProcessed, this, &Widget::handleDataProcessedSlot, Qt::QueuedConnection);

    // 连接线程的 finished 信号到 deleteLater 槽
    connect(enqueueThread, &QThread::finished, enqueueThread, &QObject::deleteLater);
    connect(dequeueThread, &QThread::finished, dequeueThread, &QObject::deleteLater);

    // 启动线程
    enqueueThread->start();
    dequeueThread->start();

    // 等待线程完成⚠️ wait 方法会阻塞主线程的事件循环，从而导致窗口无响应。
//    enqueueThread->wait();
//    dequeueThread->wait();
#endif


    qDebug() <<__TIME__<<__FUNCTION__<<__LINE__<< "currentThreadId:" << QThread::currentThreadId() << endl;
    qDebug() <<__TIME__<<__FUNCTION__<<__LINE__<< "Elapsed time:" << t.elapsed() << endl;
}

// Qt 宏单例模式（官方推荐模式）
void Widget::on_pushButton_2_clicked()
{
    CThreadSafeBuffer::getInstance()->showMessage(tr("单例模式"));

    QElapsedTimer t;
    t.start();

    //quint64 len = 2000000; // 测试多线程极限
    quint64 len = 1000;

#if 0
    // 开启两个线程,一个入队和一个出队
    // 使用std::async创建一个异步任务
    auto futureEnqueue = std::async(std::launch::async, threadFunctionEnqueue,len);

    // 使用std::async创建一个异步任务
    auto futureDequeue = std::async(std::launch::async, threadFunctionDequeue,len);

    // 等待异步任务完成
    futureEnqueue.wait();

    // 等待异步任务完成
    futureDequeue.wait();

#elif(0)
    // 开启两个线程,一个入队和一个出队
    std::thread enqueueThread(threadFunctionEnqueue, len);
    std::thread dequeueThread(threadFunctionDequeue, len);

    // 等待两个线程完成
    enqueueThread.join();
    dequeueThread.join();
#else
    // 创建两个工作线程
    enqueueThread = new WorkerThread(len, true, this);
    dequeueThread = new WorkerThread(len, false, this);
    // 连接信号和槽
    connect(enqueueThread, &WorkerThread::dataProcessed, this, &Widget::handleDataProcessedSlot, Qt::QueuedConnection);
    connect(dequeueThread, &WorkerThread::dataProcessed, this, &Widget::handleDataProcessedSlot, Qt::QueuedConnection);

    // 连接线程的 finished 信号到 deleteLater 槽
    connect(enqueueThread, &QThread::finished, enqueueThread, &QObject::deleteLater);
    connect(dequeueThread, &QThread::finished, dequeueThread, &QObject::deleteLater);

    // 启动线程
    enqueueThread->start();
    dequeueThread->start();

    // 等待线程完成⚠️ wait 方法会阻塞主线程的事件循环，从而导致窗口无响应。
//    enqueueThread->wait();
//    dequeueThread->wait();
#endif


    qDebug() <<__TIME__<<__FUNCTION__<<__LINE__<< "currentThreadId:" << QThread::currentThreadId() << endl;
    qDebug() <<__TIME__<<__FUNCTION__<<__LINE__<< "Elapsed time:" << t.elapsed() << endl;
}

// 多线程更新槽
void Widget::handleDataProcessedSlot(const QString &message)
{
    ui->textEdit->append(message);
    // 检查线程是否都已完成
    if (enqueueThread == nullptr && dequeueThread == nullptr)
        qDebug() <<__TIME__<<__FUNCTION__<<__LINE__<< QString("finish") << endl;
}
